﻿/*
** Haaf's Game Engine 1.5
** Copyright (C) 2003-2004, Relish Games
** hge.relishgames.com
**
** hgeGUI default controls header
*/
module core.hgeguictrls;

private	import		core.hgeall;
private	import 	core.dlinkedlist;


/*
#include "hge.h"
#include "hgesprite.h"
#include "hgefont.h"
#include "hgerect.h"
#include "hgegui.h"
*/

bool hgeButtonGetState(hgeGUI	gui,int id)	{
		return (cast(hgeGUIButton*)gui.GetCtrl(id)).GetState();
	}
void hgeButtonSetState(hgeGUI  	gui,int id, bool b){
		(cast(hgeGUIButton*)gui.GetCtrl(id)).SetState(b);
	}
/*float hgeSliderGetValue(hgeGUI  	gui,int id){
		return  (cast(hgeGUISlider*)gui.GetCtrl(id)).GetValue();
	}
void hgeSliderSetValue(hgeGUI  	gui,int id,float f){
		(cast(hgeGUISlider*)gui.GetCtrl(id)).SetValue(f);
	}
hgeGUIText  hgeGetTextCtrl(hgeGUI  	gui,int id){
		return (cast(hgeGUIText*)gui.GetCtrl(id));
	}
	hgeGUIListbox	 hgeGetListboxCtrl(hgeGUI  	gui,int id){
		return	(cast(hgeGUIListbox*)gui.GetCtrl(id));
	}
*/
/*
** hgeGUIText
*/
class hgeGUIText : public hgeGUIObject
{
public:
	this(int _id, float x, float y, float w, float h, hgeFontCN fnt)
	{
			id=_id;
			bStatic=true;
			bVisible=true;
			bEnabled=true;
			rect.Set(x, y, x+w, y+h);

			font=fnt;
			tx=x;
			ty=y+(h-fnt.GetHeight())/2.0f;

			col=0xFFFFFFFF;
			text =" ";
	}
		
	void	SetMode(int _align)
		{
			alig=_align;
			if(alig==HGETEXT_RIGHT) tx=rect.x2;
			else if(alig==HGETEXT_CENTER) tx=(rect.x1+rect.x2)/2.0f;
			else tx=rect.x1;
		}
	void	SetText(char[] _text)
			{
				text= _text;
			}

	void	SetColor(uint _col) { col=_col; }


	void 	printf(char[] format, ...)
			{
				//vsprintf(text, format, format.ptr+format.length);
				//wchar[] line;
				void putc(dchar c) {
					std.utf.encode(text, c);
				}
				std.format.doFormat(&putc, _arguments, _argptr);
				//delete line;		//必须使用此项,否则游戏开始2分钟后会自动退出
			}

	void 	Render()
			{
				font.SetColor(col);
				font.Render(tx,ty,alig, std.utf.toUTF16(text));
			}
private:
	hgeFontCN		font;
	float			tx, ty;
	int				alig;
	char[]			text;
	uint			col;
};


/*
** hgeGUIButton
*/
class hgeGUIButton : public hgeGUIObject
{
public:
	this(int _id, float x, float y, float w, float h, HTEXTURE tex=0, float tx=0, float ty=0)
		{
			this.id=_id;
			bStatic=false;
			bVisible=true;
			bEnabled=true;
			rect.Set(x, y, x+w, y+h);

			bPressed=false;
			bTrigger=false;

			sprUp = new hgeSprite(tex, tx, ty, w, h);
			sprDown = new hgeSprite(tex, tx+w, ty, w, h);
		}
	~this()
		{
			if(sprUp) delete sprUp;
			if(sprDown) delete sprDown;
		}

	void	SetMode(bool _bTrigger) 	{ bTrigger=_bTrigger; }
	void	SetState(bool _bPressed) 	{ bPressed=_bPressed; }
	bool	GetState() 			{ return bPressed; }

	void	Render()
	{
		if(bPressed) sprDown.Render(rect.x1, rect.y1);
		else sprUp.Render(rect.x1, rect.y1);
	}
	
	bool	MouseLButton(bool bDown)
		{
			if(bDown)
			{
				bOldState=bPressed; bPressed=true;
				return false;
			}
			else
			{
				if(bTrigger) bPressed=!bOldState;
				else bPressed=false;
				return true; 
			}
		}


private:
	bool			bTrigger;
	bool			bPressed;
	bool			bOldState;
	hgeSprite		sprUp, sprDown;
};









//*******************************************
//*******************************************







// hgeGUISlider

const HGESLIDER_BAR			=0;
const HGESLIDER_BARRELATIVE	=1;
const HGESLIDER_SLIDER			=2;

class hgeGUISlider : public hgeGUIObject
{
public:
	this(int _id, float x, float y, float w, float h, HTEXTURE tex, float tx, float ty, float sw, float sh, bool vertical=false)
	{
		id=_id;
		bStatic=false;
		bVisible=true;
		bEnabled=true;
		bPressed=false;
		bVertical=vertical;
		rect.Set(x, y, x+w, y+h);

		mode=HGESLIDER_BAR;
		fMin=0; fMax=100; fVal=50;
		sl_w=sw; sl_h=sh;

		sprSlider=new hgeSprite(tex, tx, ty, sw, sh);
	}


	~this()
	{
		if(sprSlider) delete sprSlider;
	}

	void	SetMode(float _fMin, float _fMax, int _mode) { fMin=_fMin; fMax=_fMax; mode=_mode; }
	void	SetValue(float _fVal)
	{
		if(_fVal<fMin) fVal=fMin;
		else if(_fVal>fMax) fVal=fMax;
		else fVal=_fVal;
	}
	float	GetValue()		{ return fVal; }

	void	Render()
	{
		float xx, yy;
		float x1,y1,x2,y2;

		xx=rect.x1+(rect.x2-rect.x1)*(fVal-fMin)/(fMax-fMin);
		yy=rect.y1+(rect.y2-rect.y1)*(fVal-fMin)/(fMax-fMin);
		
		if(bVertical)
			switch(mode)
			{
				case HGESLIDER_BAR: x1=rect.x1; y1=rect.y1; x2=rect.x2; y2=yy; break;
				case HGESLIDER_BARRELATIVE: x1=rect.x1; y1=(rect.y1+rect.y2)/2; x2=rect.x2; y2=yy; break;
				case HGESLIDER_SLIDER: x1=(rect.x1+rect.x2-sl_w)/2; y1=yy-sl_h/2; x2=(rect.x1+rect.x2+sl_w)/2; y2=yy+sl_h/2; break;
			}
		else
			switch(mode)
			{
				case HGESLIDER_BAR: x1=rect.x1; y1=rect.y1; x2=xx; y2=rect.y2; break;
				case HGESLIDER_BARRELATIVE: x1=(rect.x1+rect.x2)/2; y1=rect.y1; x2=xx; y2=rect.y2; break;
				case HGESLIDER_SLIDER: x1=xx-sl_w/2; y1=(rect.y1+rect.y2-sl_h)/2; x2=xx+sl_w/2; y2=(rect.y1+rect.y2+sl_h)/2; break;
			}
		sprSlider.RenderStretch(x1, y1, x2, y2);
	}

	bool	MouseMove(float x, float y)
	{
		if(bPressed)
		{
			if(bVertical)
			{
				if(y>rect.y2-rect.y1) y=rect.y2-rect.y1;
				if(y<0) y=0;
				fVal=fMin+(fMax-fMin)*y/(rect.y2-rect.y1);
			}
			else
			{
				if(x>rect.x2-rect.x1) x=rect.x2-rect.x1;
				if(x<0) x=0;
				fVal=fMin+(fMax-fMin)*x/(rect.x2-rect.x1);
			}
			return true;
		}

		return false;
	}


	bool	MouseLButton(bool bDown)
	{
		bPressed=bDown;
		return false;
	}

private:
	bool			bPressed;
	bool			bVertical;
	int				mode;
	float			fMin, fMax, fVal;
	float			sl_w, sl_h;
	hgeSprite		sprSlider;
};





// hgeGUIListbox



alias		dlinkedlist!(char[])		linklist;		// 模板别名 

class hgeGUIListbox : public hgeGUIObject
{
public:
	this(int _id, float x, float y, float w, float h, hgeFontCN fnt, uint tColor=0xff000000, uint thColor=0xff002222, uint hColor=0x66ff0000)
	{
		id=_id;
		bStatic=false;
		bVisible=true;
		bEnabled=true;
		rect.Set(x, y, x+w, y+h);
		font=fnt;
		sprHighlight=new hgeSprite(0, 0, 0, w, fnt.GetHeight());
		sprHighlight.SetColor(hColor);
		textColor=tColor;
		texthilColor=thColor;

		nSelectedItem=0;
		nTopItem=0;
		mx=0; my=0;

		lnk= new linklist;
	}
	
	~this()
	{
		Clear();
		if(sprHighlight) delete sprHighlight;
	}

	void AddItem(char[] item)
	{
		lnk.add(item);
	}
	
	void DeleteItem(int n)
	{
		if(n<0 || n>=lnk.length) return;

		lnk.reset;		// 链表回位
		uint j=0;
		while(!lnk.last)
		{
			if(j==n)
			{
				lnk.remove; 
				break;
			}
			j++;
		}
	}

	
	int		GetSelectedItem() 		{ return nSelectedItem; }
	void	SetSelectedItem(int n) 	{ if(n>=0 && n<GetNumItems()) nSelectedItem=n; }
	int		GetTopItem() 			{ return nTopItem; }
	void	SetTopItem(int n) 		{ if(n>=0 && n<=GetNumItems()-GetNumRows()) nTopItem=n; }

	char[]	GetItemText(int n)
		{			
			if(n<0 || n>=lnk.length) return null;

			lnk.reset;	uint j=0;
			while(!lnk.last)
			{
				if(j==n)
				{
					return lnk.data;
				}
			}
			return	null;
		}

	int		nItems()		{ return lnk.length;	}
	int		GetNumItems() 	{ return nItems; }
	int		GetNumRows() 	{ return cast(int)((rect.y2-rect.y1)/font.GetHeight()); }
	void	Clear()			{ lnk.clear;	}

	void Render()
	{
		hgeFontCN.vmes("lnk size======",lnk.size,"行数==",GetNumRows(),"items==",nItems);
		if(lnk.empty) return;

		lnk.reset;

		int hang=GetNumRows();
		int i=0;
		while(! lnk.last)
		{	if(i>=hang) break;
		
		
			if(nTopItem+i == nSelectedItem)
			{
				sprHighlight.Render(rect.x1,rect.y1+i*font.GetHeight());
				font.SetColor(texthilColor);
			}
			else font.SetColor(textColor);
			font.Render(rect.x1+3, rect.y1+i*font.GetHeight(), HGETEXT_LEFT, std.utf.toUTF16(lnk.data));
			i++;
		}	
	}
	
	bool MouseMove(float x, float y) { mx=x; my=y; return false; }
	bool MouseLButton(bool bDown)
	{
		int nItem;
		if(bDown)
		{
			nItem=nTopItem+cast(int)(my)/ cast(int)(font.GetHeight());
			if(nItem<nItems)
			{
				nSelectedItem=nItem;
				return true;
			}
		}
		return false;
	}

	bool MouseWheel(int nNotches)
	{
		nTopItem-=nNotches;
		if(nTopItem<0) nTopItem=0;
		if(nTopItem>GetNumItems()-GetNumRows()) nTopItem=GetNumItems()-GetNumRows();

		return true;
	}

	bool KeyClick(int key, int chr)
	{
		switch(key)
		{
			case HGEK_DOWN:
				if(nSelectedItem < nItems-1)
				{
					nSelectedItem++;
					if(nSelectedItem > nTopItem+GetNumRows()-1) nTopItem=nSelectedItem-GetNumRows()+1;
					return true;
				}
				break;

			case HGEK_UP:
				if(nSelectedItem > 0)
				{
					nSelectedItem--;
					if(nSelectedItem < nTopItem) nTopItem=nSelectedItem;
					return true;
				}
				break;
			default:
				break;
		}
		return false;
	}


private:
	hgeSprite		sprHighlight;
	hgeFontCN			font;
	uint			textColor, texthilColor;

	int				 nSelectedItem, nTopItem;
	float				mx, my;
	linklist		lnk;
};



